#include "mainwindow.h"
#include "qwt_plot.h"
#include "qwt_plot_curve.h"
#include "qwt_plot_grid.h"
#include "qwt_scale_widget.h"
#include "qwt_text.h"

#include <QtDebug>

MainWindow::MainWindow() : QMainWindow()
{
    this->setWindowIcon(QIcon(":/images/plot.png"));

    plotter = new Plotter(this);
    this->setCentralWidget(plotter);

    fileMenu = menuBar()->addMenu(tr("&File"));
    plotMenu = menuBar()->addMenu(tr("&Plot"));
    viewMenu = menuBar()->addMenu(tr("&View"));
    helpMenu = menuBar()->addMenu(tr("&Help"));

    changeHomeAction = fileMenu->addAction(QIcon(":/images/directory.png") ,tr("&Home"));
    fileMenu->addSeparator();
    saveImagAction = fileMenu->addAction(QIcon(":/images/image_save.png"), tr("Save &Image"));
    saveDataAction = fileMenu->addAction(QIcon(":/images/data_save.png"), tr("Save &Data"));
    fileMenu->addSeparator();
    exitAction = fileMenu->addAction(tr("E&xit"));
    updatePlotAction = plotMenu->addAction(QIcon(":/images/refresh.png"), tr("&Update"));
    plotMenu->addSeparator();
    zoomingAction = plotMenu->addAction(QIcon(":/images/zoom.png"), tr("Zooming"));
    plotMenu->addSeparator();
    showGridAction = plotMenu->addAction(QIcon(":/images/grid.png"), tr("Show Grid"));
    showLineAction = plotMenu->addAction(QIcon(":/images/curve.png"), tr("Show Line"));
    showDotsAction = plotMenu->addAction(QIcon(":/images/curve_dot.png"), tr("Show Dots"));
    aboutAction   = helpMenu->addAction(tr("&About"));
    aboutQtAction = helpMenu->addAction(tr("About &Qt"));

    zoomingAction->setCheckable(true);
    showGridAction->setCheckable(true);
    showLineAction->setCheckable(true);
    showDotsAction->setCheckable(true);
    zoomingAction->setChecked(plotter->isZoomingEnabled());
    showGridAction->setChecked(plotter->isGridVisible());
    showLineAction->setChecked(plotter->isLineVisible());
    showDotsAction->setChecked(plotter->isDataVisible());

    QToolBar* mainBar = this->addToolBar(tr("Main Toolbar"));
    mainBar->addAction(changeHomeAction);
    mainBar->addAction(saveImagAction);
    mainBar->addAction(saveDataAction);
    mainBar->addAction(updatePlotAction);
    mainBar->addAction(zoomingAction);
    mainBar->addAction(showGridAction);
    mainBar->addAction(showLineAction);
    mainBar->addAction(showDotsAction);

    QToolBar* xBar = this->addToolBar(tr("X Axis Toolbar"));

    xCombo = new QComboBox(this);
    xSpin = new QDoubleSpinBox(this);

    //xCombo->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
    xCombo->setSizeIncrement(10, 5);
    xSpin->setValue(1);
    xSpin->setMaximum(1000);

    xBar->addWidget(xCombo);
    xBar->addSeparator();
    xBar->addWidget(xSpin);

    xPlusAction = xBar->addAction(QIcon(":/images/plus.png"),     tr("Plus"));
    xMinuAction = xBar->addAction(QIcon(":/images/minus.png"),    tr("Minus"));
    xMultAction = xBar->addAction(QIcon(":/images/multiply.png"), tr("Multiply"));
    xDiviAction = xBar->addAction(QIcon(":/images/divide.png"),   tr("Divide"));

    QToolBar* yBar = this->addToolBar(tr("Y Axis Toolbar"));

    yCombo = new QComboBox(this);
    ySpin = new QDoubleSpinBox(this);

    //yCombo->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
    yCombo->setSizeIncrement(10, 5);
    ySpin->setValue(1);
    ySpin->setMaximum(1000);

    yBar->addWidget(yCombo);
    yBar->addSeparator();
    yBar->addWidget(ySpin);

    yPlusAction = yBar->addAction(QIcon(":/images/plus.png"),     tr("Plus"));
    yMinuAction = yBar->addAction(QIcon(":/images/minus.png"),    tr("Minus"));
    yMultAction = yBar->addAction(QIcon(":/images/multiply.png"), tr("Multiply"));
    yDiviAction = yBar->addAction(QIcon(":/images/divide.png"),   tr("Divide"));

    fileView = new QTreeView(this);
    dirModel = new QFileSystemModel(this);
    dockWidget = new QDockWidget(tr("Files"), this);

    dirModel->setNameFilters(QStringList() << "*.dat");
    dirModel->setNameFilterDisables(false);
    fileView->setModel(dirModel);
    fileView->setHeaderHidden(true);
    for(int i=1; i<dirModel->columnCount(); i++)
    {
        fileView->setColumnHidden(i, true);
    }
    dockWidget->setWidget(fileView);

    this->addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
    viewMenu->addAction(dockWidget->toggleViewAction());

    connect(changeHomeAction, SIGNAL(triggered()), this, SLOT(changeHome()));
    connect(saveImagAction, SIGNAL(triggered()), this, SLOT(savePlotImage()));
    connect(saveDataAction, SIGNAL(triggered()), this, SLOT(savePlotData()));
    connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
    connect(updatePlotAction, SIGNAL(triggered()), this, SLOT(updatePlot()));
    connect(zoomingAction, SIGNAL(toggled(bool)), plotter, SLOT(setZoomingEnabled(bool)));
    connect(showGridAction, SIGNAL(toggled(bool)), plotter, SLOT(setGridVisible(bool)));
    connect(showLineAction, SIGNAL(toggled(bool)), plotter, SLOT(setLineVisible(bool)));
    connect(showDotsAction, SIGNAL(toggled(bool)), plotter, SLOT(setDataVisible(bool)));
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
    connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));

    connect(xPlusAction, SIGNAL(triggered()), this, SLOT(xPlus()));
    connect(xMinuAction, SIGNAL(triggered()), this, SLOT(xMinus()));
    connect(xMultAction, SIGNAL(triggered()), this, SLOT(xMultiply()));
    connect(xDiviAction, SIGNAL(triggered()), this, SLOT(xDivide()));
    connect(yPlusAction, SIGNAL(triggered()), this, SLOT(yPlus()));
    connect(yMinuAction, SIGNAL(triggered()), this, SLOT(yMinus()));
    connect(yMultAction, SIGNAL(triggered()), this, SLOT(yMultiply()));
    connect(yDiviAction, SIGNAL(triggered()), this, SLOT(yDivide()));

    connect(fileView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), this, SLOT(updatePlot(QModelIndex)));

    readSettings();

    statusBar()->showMessage(tr("Welcome!"), 5000);
}


void MainWindow::changeHome()
{
    QString path = QFileDialog::getExistingDirectory(this, tr("Select a directory"), homepath, QFileDialog::ShowDirsOnly);

    if(!path.isEmpty())
    {
        homepath = path;
        dirModel->setRootPath(path);
        fileView->setRootIndex(dirModel->index(path));
    }
}

void MainWindow::doUpdatePlot()
{
    Project& project = getProject(filepath);

    if(project.isValid())
    {
        QString xColumnName = xCombo->currentText();
        QString yColumnName = yCombo->currentText();
        QVector<double>& xData = project.xColumnData(xColumnName);
        QVector<double>& yData = project.yColumnData(yColumnName);

        plotter->update(xColumnName, xData, yColumnName, yData);
    }
}

void MainWindow::updatePlot()
{
    Project& project = getProject(filepath);

    if(project.isValid())
    {
        project.update();

        doUpdatePlot();
    }
}

void MainWindow::updatePlot(const QModelIndex& index)
{
    filepath = dirModel->filePath(index);

    statusBar()->showMessage(filepath);

    disconnect(xCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePlot()));
    disconnect(yCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePlot()));

    xCombo->clear();
    yCombo->clear();

    Project& project = getProject(filepath);

    if(project.isValid())
    {
        xCombo->addItems(project.xColumnNames());
        yCombo->addItems(project.yColumnNames());

        if(project.xColumnNames().first() != project.yColumnNames().first())
        {
            xCombo->setCurrentIndex(0);
            yCombo->setCurrentIndex(0);
        }
        else
        {
            xCombo->setCurrentIndex(0);
            yCombo->setCurrentIndex(1);
        }

        connect(xCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePlot()));
        connect(yCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePlot()));

        doUpdatePlot();
    }
}

void MainWindow::savePlotImage()
{
    QString targetPath = QFileDialog::getSaveFileName(this, tr("Save Image"), homepath);

    if(!targetPath.isEmpty())
    {
        plotter->saveImage(targetPath);
    }
}

void MainWindow::savePlotData()
{
    QString targetPath = QFileDialog::getSaveFileName(this, tr("Save Data"), homepath);

    if(!targetPath.isEmpty())
    {
        plotter->saveData(targetPath);
    }
}

void MainWindow::xPlus()
{
    Project& project = getProject(filepath);

    if(project.isValid())
    {
        project.update(xCombo->currentText(), Project::Plus, xSpin->value());

        doUpdatePlot();
    }
}

void MainWindow::xMinus()
{
    Project& project = getProject(filepath);

    if(project.isValid())
    {
        project.update(xCombo->currentText(), Project::Minus, xSpin->value());

        doUpdatePlot();
    }
}

void MainWindow::xMultiply()
{
    Project& project = getProject(filepath);

    if(project.isValid())
    {
        project.update(xCombo->currentText(), Project::Multiply, xSpin->value());

        doUpdatePlot();
    }
}

void MainWindow::xDivide()
{
    Project& project = getProject(filepath);

    if(project.isValid())
    {
        project.update(xCombo->currentText(), Project::Devide, xSpin->value());

        doUpdatePlot();
    }
}

void MainWindow::yPlus()
{
    Project& project = getProject(filepath);

    if(project.isValid())
    {
        project.update(yCombo->currentText(), Project::Plus, ySpin->value());

        doUpdatePlot();
    }
}

void MainWindow::yMinus()
{
    Project& project = getProject(filepath);

    if(project.isValid())
    {
        project.update(yCombo->currentText(), Project::Minus, ySpin->value());

        doUpdatePlot();
    }
}

void MainWindow::yMultiply()
{
    Project& project = getProject(filepath);

    if(project.isValid())
    {
        project.update(yCombo->currentText(), Project::Multiply, ySpin->value());

       doUpdatePlot();
    }
}

void MainWindow::yDivide()
{
    Project& project = getProject(filepath);

    if(project.isValid())
    {
        project.update(yCombo->currentText(), Project::Devide, ySpin->value());

        doUpdatePlot();
    }
}

void MainWindow::about()
{
    QMessageBox::about(this,
                       tr("About Squirrel"),
                       tr("<html><b>Squirrel</b> is a simple data viewer."
                          "<br><br>Copyright &copy; Freedomsoft 2009-2013</html>"));
}


Project& MainWindow::getProject(const QString &filepath)
{
    if(!projects.contains(filepath))
    {
        projects[filepath] = Project(filepath);
    }
    return projects[filepath];
}

void MainWindow::readSettings()
{
    QSettings settings("Freedomsoft", "Squirrel");
    QString path     = settings.value("home", QDir::homePath()).toString();
    QPoint  position = settings.value("pos",  QPoint(200, 200)).toPoint();
    QSize   size     = settings.value("size", QSize(800, 500)).toSize();

    this->move(position);
    this->resize(size);

    homepath = path;
    dirModel->setRootPath(path);
    fileView->setRootIndex(dirModel->index(path));
}

void MainWindow::writeSettings()
{
    QSettings settings("Freedomsoft", "Squirrel");
    settings.setValue("home", this->homepath);
    settings.setValue("pos",  this->pos());
    settings.setValue("size", this->size());
}

void MainWindow::closeEvent(QCloseEvent* event) {
    Q_UNUSED(event);
    writeSettings();
}
